package com.dinglian.ots.service.impl;

import cn.hutool.core.util.StrUtil;
import com.dinglian.ots.common.ToolUtils;
import com.dinglian.ots.common.model.Constant;
import com.dinglian.ots.dao.mapper.*;
import com.dinglian.ots.dao.model.*;
import com.dinglian.ots.exception.GlobalException;
import com.dinglian.ots.result.CodeMsg;
import com.dinglian.ots.service.BrandService;
import com.dinglian.ots.service.CartService;
import com.dinglian.ots.service.OrderService;
import com.dinglian.ots.vo.cart.*;
import com.dinglian.ots.vo.user.UserVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * @author wangbo
 */
@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private CartMapper cartMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private BrandRuleMapper brandRuleMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderListMapper orderListMapper;

    @Autowired
    private BrandMapper brandMapper;

    @Autowired
    private OrderServiceImpl orderService;

    @Autowired
    private BrandService brandService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCart(CartVo cartVo) {

        Integer productId = cartVo.getProductId();
        Product product = productMapper.selectByPrimaryKey(productId);

        if (product == null) {
            throw new GlobalException(CodeMsg.PRODUCT_IS_NULL);
        }

        Session session = SecurityUtils.getSubject().getSession();
        UserVo userVo = (UserVo) session.getAttribute(Constant.SESSION_USER);
        if (userVo!=null){
            String roleName = userVo.getRoleName();
            if (Constant.BUYER_ROLE_NAME.equals(roleName)) {
                Integer userId = userVo.getUserId();
                boolean result = brandService.isAuthSuccess(userId, product.getBrandId());
                if (!result) {
                    throw new GlobalException(CodeMsg.BRAND_IS_NOT_PASS);
                }
            }
        }

        Integer costPrice = product.getCostPrice();

        // 查询用户是否存在当季订单
        Order order = orderMapper.existElectionOrderSeason(cartVo.getUserId(), productId);
        if (order == null) {
            List<CartSkuVo> cartSkuVos = cartVo.getSkuList();
            for (int i = 0; i < cartSkuVos.size(); i++) {
                CartSkuVo cartSkuVo = cartSkuVos.get(i);
                Integer skuId = cartSkuVo.getSkuId();
                Integer qty = cartSkuVo.getQuantity();
                CartExample cartExample = new CartExample();
                cartExample.or().andSkuIdEqualTo(skuId).andUserIdEqualTo(cartVo.getUserId());
                List<Cart> carts = cartMapper.selectByExample(cartExample);
                if (!carts.isEmpty()) {
                    Cart cart = carts.get(0);
                    Integer quantity = cart.getQuantity();
                    quantity = qty + quantity;
                    cart.setQuantity(quantity);
                    cart.setAmount((new BigDecimal(quantity).multiply(new BigDecimal(costPrice))).longValue() );
                    cartMapper.updateByPrimaryKeySelective(cart);
                } else {
                    Cart cart = new Cart();
                    cart.setUserId(cartVo.getUserId());
                    cart.setProductId(productId);
                    cart.setSkuId(skuId);
                    cart.setQuantity(qty);
                    cart.setAmount((new BigDecimal(costPrice).multiply(new BigDecimal(qty))).longValue() );
                    cartMapper.insertSelective(cart);
                }
            }
            Integer qty = cartMapper.getAllTotalQty(productId,userVo.getUserId());
            Integer colorMinimum = product.getColorMinimum();
            if (qty < colorMinimum) {
                throw new GlobalException(CodeMsg.LESS_THAN_MINIMUM_ORDER_QTY1);
            }

        } else {
          /*  // 检查最小起订量是否达标
            // 查询各各商品最小起订量
            Map<Integer, Integer> productMinimumOrderMap = new HashMap<>();
            // 暂时只检查单色最小订量
            Integer colorMinimum = product.getColorMinimum();
            if (colorMinimum != null) {
                productMinimumOrderMap.put(productId, colorMinimum);
            }*/

            // 存在则直接加入到选款单中
            for (CartSkuVo cartSkuVo : cartVo.getSkuList()) {
                OrderListExample orderListExample = new OrderListExample();
                orderListExample.or().andOrderIdEqualTo(order.getId()).andSkuIdEqualTo(cartSkuVo.getSkuId());
                List<OrderList> orderLists = orderListMapper.selectByExample(orderListExample);
                if (orderLists.isEmpty()) {
                    OrderList orderList = new OrderList();
                    orderList.setOrderId(order.getId());
                    orderList.setSkuId(cartSkuVo.getSkuId());
                    orderList.setQty(cartSkuVo.getQuantity());
                    orderList.setProductId(productId);
                    long amt = costPrice * cartSkuVo.getQuantity();
                    orderList.setAmt(amt);
                  /*  // 存在最小定量检查
                    if (productMinimumOrderMap.containsKey(productId)) {
                        if (orderList.getQty() < productMinimumOrderMap.get(productId)) {
                            throw new GlobalException(CodeMsg.LESS_THAN_MINIMUM_ORDER_QTY);
                        }
                    }*/

                    orderListMapper.insertSelective(orderList);
                } else {
                    OrderList orderList = orderLists.get(0);
                    orderList.setQty(orderList.getQty() + cartSkuVo.getQuantity());
                    long amt = costPrice * orderList.getQty();
                    orderList.setAmt(amt);


                    /*// 存在最小定量检查
                    if (productMinimumOrderMap.containsKey(productId)) {
                        if (orderList.getQty() < productMinimumOrderMap.get(productId)) {
                            throw new GlobalException(CodeMsg.LESS_THAN_MINIMUM_ORDER_QTY);
                        }
                    }*/

                    orderListMapper.updateByPrimaryKeySelective(orderList);
                }
            }

            orderMapper.updateTotal(order.getId());

            //计算折后价格
            List<Map> brandList = orderListMapper.getBrandTotal(cartVo.getUserId());
            for (int i = 0; i < brandList.size(); i++) {
                Map map = brandList.get(i);
                BigDecimal balance = orderService.calculateLadderPrice(map);
                if (balance.longValue() < 0) {
                    balance = new BigDecimal(0);
                }
                Integer brandId = (Integer) map.get("brandId");
                orderListMapper.updateBalance(order.getId(), brandId, balance.multiply(new BigDecimal(100)));
            }
        }
    }

    @Override
    public Map updateCart(UpdateCartVo cartVo) {
        Integer userId = cartVo.getUserId();
        Integer skuId = cartVo.getSkuId();

        Map skuMap = skuMapper.selectProductPrice(skuId);
        String costPriceStr = ToolUtils.objectToString(skuMap.get("costPrice"));
        Integer costPrice = 0;
        if (!StrUtil.isBlank(costPriceStr)){
            costPrice = Integer.valueOf(costPriceStr);
        }

        Integer quantity = cartVo.getQuantity();
        CartExample cartExample = new CartExample();
        cartExample.or().andUserIdEqualTo(userId).andSkuIdEqualTo(skuId);
        Cart cart = new Cart();
        cart.setQuantity(quantity);
        cart.setAmount((new BigDecimal(quantity).multiply(new BigDecimal(costPrice))).longValue());
        cartMapper.updateByExampleSelective(cart, cartExample);


        //判断单色起订量
        Map pMap = cartMapper.getProductTotalBySkuId(userId,skuId);
        BigDecimal qty = (BigDecimal) pMap.get("qty");
        String miniQty = ToolUtils.objectToString(pMap.get("miniQty"));
        String stylename = (String) pMap.get("stylename");
        if (miniQty != null){
            if (qty.compareTo(new BigDecimal(miniQty))==-1){
                throw new GlobalException(CodeMsg.LESS_THAN_MINIMUM_ORDER_QTY.fillArgs(stylename));
            }
        }


        Map map = cartMapper.getProductTotal(userId, skuId);
        Integer brandId = (Integer) map.get("id");
        BigDecimal totalAmount = (BigDecimal) map.get("amt");
        BigDecimal totalQuantity = (BigDecimal) map.get("qty");

      /*  //判断品牌起订量
        BrandWithBLOBs brandWithBLOBs = brandMapper.selectByPrimaryKey(brandId);
        String miniOrderQuantity = brandWithBLOBs.getMiniOrderQuantity();
        if (miniOrderQuantity != null){
            if (totalAmount.compareTo(new BigDecimal(miniOrderQuantity))==-1){
                throw  new GlobalException(CodeMsg.LESS_THAN_MINIMUM_BRAND_QTY);
            }
        }*/
        BigDecimal price = new BigDecimal(costPrice).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP);
        //计算阶梯价格
        String content = calculateLadderPrice(brandId, totalAmount, totalQuantity.intValue());
        Map productMap = new HashMap();
        productMap.put("content", content);
        productMap.put("amt", price.multiply(qty).setScale(2));
        BigDecimal balance = calculateLadderPrice1(brandId, totalAmount, totalQuantity.intValue());
        productMap.put("balance",balance);

        return productMap;
//        cartMapper.updateCart(cartVo);
    }


    @Override
    public CartListVo getCartList(Integer userId) {

        //获取购物车中品牌信息
        List<BrandCartVo> brandCartVos = cartMapper.getBrandCart(userId);
        BigDecimal totalCartAmt = BigDecimal.ZERO;
        for (int i = 0; i < brandCartVos.size(); i++) {
            BrandCartVo brandCartVo = brandCartVos.get(i);
            Integer brandId = brandCartVo.getBrandId();
            //获取购物车中产品信息
            List<Map> productCartList = cartMapper.getProductCart(userId, brandId);
            List<ProductCartVo> productCartVos = new ArrayList<>();
            BigDecimal totalBrandAmt = BigDecimal.ZERO;
            Integer totalBrandQty = 0;
            //用于产品的归类
            Map productMap = new HashMap();
            for (int j = 0; j < productCartList.size(); j++) {
                Map map = productCartList.get(j);
                Integer productId = (Integer) map.get("id");
                String name = (String) map.get("name");
                String title = (String) map.get("title");
                String thumbnail = (String) map.get("thumbnail");
                String colorName = (String) map.get("colorName");
                String stylename = (String) map.get("stylename");
                Long colorMinimum = (Long) map.get("colorMinimum");
                BigDecimal costPrice = (BigDecimal) map.get("costPrice");
                BigDecimal sellingPrice = (BigDecimal) map.get("sellingPrice");
                String sizeName = (String) map.get("sizeName");
                Integer quantity = (Integer) map.get("quantity");
                Integer skuId = (Integer) map.get("skuId");
                BigDecimal amt = (BigDecimal) map.get("amt");
                Map sizeMap = new HashMap();
                sizeMap.put("skuId", skuId);
                sizeMap.put("sizeName", sizeName);
                sizeMap.put("qty", quantity);


                ProductCartVo productCartVo = (ProductCartVo) productMap.get(productId);
                if (productCartVo == null) {
                    productCartVo = new ProductCartVo();
                    productCartVo.setProductId(productId);
                    productCartVo.setName(name);
                    productCartVo.setTitle(title);
                    productCartVo.setColorName(colorName);
                    productCartVo.setCostPrice(costPrice.setScale(2, RoundingMode.HALF_UP).doubleValue());
                    productCartVo.setSellingPrice(sellingPrice.setScale(2, RoundingMode.HALF_UP).doubleValue());
                    productCartVo.setThumbnail(thumbnail);
                    productCartVo.setStylename(stylename);
                    productCartVo.setColorMinimum(colorMinimum);
                    List<Map> sizeCartList = new ArrayList<>();
                    sizeCartList.add(sizeMap);
                    productCartVo.setSizeList(sizeCartList);
                    productCartVo.setTotalAmt(amt);

                    productMap.put(productId, productCartVo);
                    productCartVos.add(productCartVo);
                } else {
                    List<Map> sizeList = productCartVo.getSizeList();
                    sizeList.add(sizeMap);
                    BigDecimal totalAmt = productCartVo.getTotalAmt();
                    productCartVo.setTotalAmt(totalAmt.add(amt));
                }
                totalBrandAmt = totalBrandAmt.add(amt);
                totalBrandQty += quantity;
            }
            brandCartVo.setProductCartList(productCartVos);

//            BigDecimal totalAmount = brandCartVo.getTotalAmount();
//            Integer totalQuantity = brandCartVo.getTotalQuantity();

            BigDecimal balance = calculateLadderPrice1(brandId, totalBrandAmt, totalBrandQty);

            brandCartVo.setTotalAmount(balance);
            //计算阶梯价格
            String content = calculateLadderPrice(brandId, totalBrandAmt, totalBrandQty);
            brandCartVo.setContent(content);

            totalCartAmt = totalCartAmt.add(balance);
        }
        CartListVo cartListVo = new CartListVo();
        cartListVo.setTotalAmt(totalCartAmt.setScale(2, RoundingMode.HALF_UP).doubleValue());
        cartListVo.setBrandCartList(brandCartVos);

        return cartListVo;
    }

    /**
     * 计算阶梯价格
     *
     * @return
     */
    private String calculateLadderPrice(Integer brandId, BigDecimal totalAmount, Integer totalQuantity) {

        //先判断是否含有金额规则或者数量规则
        BrandRuleExample amtbrandRuleExample = new BrandRuleExample();
        amtbrandRuleExample.or().andBrandIdEqualTo(brandId).andOrderRuleEqualTo(1);
        List<BrandRule> amtbrandRuleList = brandRuleMapper.selectByExample(amtbrandRuleExample);

        BrandRuleExample qtybrandRuleExample = new BrandRuleExample();
        qtybrandRuleExample.or().andBrandIdEqualTo(brandId).andOrderRuleEqualTo(2);
        List<BrandRule> qtyBrandRuleList = brandRuleMapper.selectByExample(qtybrandRuleExample);
        String content = "";

        List<BigDecimal> discountList = new ArrayList<>();
        Map discountMap = new HashMap();

        if (!amtbrandRuleList.isEmpty()) {
            //金额
            List<Map> brandRules = brandRuleMapper.selectAmtRuleByBrandId(brandId, totalAmount);
            if (brandRules.isEmpty()) {
                //满足条件
                List<Map> list = brandRuleMapper.satisfyAmtCondition(brandId, totalAmount);
                if (!list.isEmpty()) {
                    Map brandRule = list.get(0);
                    //已减金额
                    String discount = ToolUtils.objectToString(brandRule.get("discount"));
                    BigDecimal bigDiscount = new BigDecimal(discount);
                    discountList.add(bigDiscount);
                    //满足金额
                    String standardAmount1 = ToolUtils.objectToString(brandRule.get("standardAmount"));
                    content = "金额已达到" + new BigDecimal(standardAmount1).doubleValue() + "元，已优惠" + new BigDecimal(discount).setScale(2,BigDecimal.ROUND_HALF_UP) + "元。";
                    discountMap.put(bigDiscount.toString(), content);
                }
            } else {
                Map brandRule = brandRules.get(0);
                //优惠金额
                String discount = ToolUtils.objectToString(brandRule.get("discount"));
                BigDecimal bigDiscount = new BigDecimal(discount);
                discountList.add(bigDiscount);
                //差值
                String difference = ToolUtils.objectToString(brandRule.get("difference"));
                content = "距下一级阶段还差" + new BigDecimal(difference).setScale(2,BigDecimal.ROUND_HALF_UP) + "元。";
                discountMap.put(discount.toString(), content);
            }
        }
        if (!qtyBrandRuleList.isEmpty()) {
            //数量
            List<Map> brandRules = brandRuleMapper.selectQtyRuleByBrandId(brandId, totalQuantity, totalAmount);
            if (brandRules.isEmpty()) {
                //满足条件
                List<Map> list = brandRuleMapper.satisfyQtyCondition(brandId, totalQuantity, totalAmount);
                if (!list.isEmpty()) {
                    Map brandRule = list.get(0);
                    //已减金额
                    String discount = ToolUtils.objectToString(brandRule.get("discount"));
                    //满足数量
                    String standardQty = ToolUtils.objectToString(brandRule.get("standardAmount"));
                    BigDecimal bigDiscount = new BigDecimal(discount);
                    discountList.add(bigDiscount);
                    content = "数量已达到" + new BigDecimal(standardQty).intValue() + "件，已优惠" + new BigDecimal(discount).setScale(2,BigDecimal.ROUND_HALF_UP)  + "元。";
                    discountMap.put(bigDiscount.toString(), content);
                }

            } else {
                Map brandRule = brandRules.get(0);
                //优惠金额
                String discount = ToolUtils.objectToString(brandRule.get("discount"));
                //差值
                String difference = ToolUtils.objectToString(brandRule.get("difference"));
                BigDecimal bigDiscount = new BigDecimal(discount);
                discountList.add(bigDiscount);
                content = "距下一级阶段还差" + new BigDecimal(difference).setScale(2,BigDecimal.ROUND_HALF_UP)  + "件。";
                discountMap.put(discount.toString(), content);
            }
        }

        if (discountList.isEmpty()) {
            content = "暂无优惠";
        } else {
            BigDecimal max = Collections.max(discountList);
            content = ToolUtils.objectToString(discountMap.get(max.toString()));
        }
        return content;
    }


    /**
     * 计算折后价格
     */
    public BigDecimal calculateLadderPrice1(Integer brandId, BigDecimal totalAmt, Integer totalQty) {


        //先判断是否含有金额规则或者数量规则
        BrandRuleExample amtbrandRuleExample = new BrandRuleExample();
        amtbrandRuleExample.or().andBrandIdEqualTo(brandId).andOrderRuleEqualTo(1);
        List<BrandRule> amtbrandRuleList = brandRuleMapper.selectByExample(amtbrandRuleExample);

        BrandRuleExample qtybrandRuleExample = new BrandRuleExample();
        qtybrandRuleExample.or().andBrandIdEqualTo(brandId).andOrderRuleEqualTo(2);
        List<BrandRule> qtyBrandRuleList = brandRuleMapper.selectByExample(qtybrandRuleExample);

        List<BigDecimal> balanceList = new ArrayList<>();

        if (!amtbrandRuleList.isEmpty()) {
            //金额
            List<Map> brandRules = brandRuleMapper.getAmtRuleByBrandId(brandId, totalAmt);
            if (brandRules.isEmpty()) {
               /* //满足最高条件
                List<Map> list = brandRuleMapper.satisfyAmtOrderCondition(brandId, totalAmt);
                if (!list.isEmpty()) {
                    Map brandRule = list.get(0);
                    String balance = ToolUtils.objectToString(brandRule.get("balance"));
                    BigDecimal bigDecimal = new BigDecimal(balance);
                    balanceList.add(bigDecimal);
                } else {
                    balanceList.add(new BigDecimal(totalAmt));
                }*/
            } else {
                Map brandRule = brandRules.get(0);
                Double balance = (Double) brandRule.get("balance");
                balanceList.add(new BigDecimal(balance));
            }
        }
        if (!qtyBrandRuleList.isEmpty()) {
            //数量
            List<Map> brandRules = brandRuleMapper.getQtyRuleByBrandId(brandId, totalQty, totalAmt);
            if (brandRules.isEmpty()) {
                /*//满足条件
                List<Map> list = brandRuleMapper.satisfyQtyOrderCondition(brandId, totalQty, totalAmt);
                if (!list.isEmpty()) {
                    Map brandRule = list.get(0);
                    String balance = ToolUtils.objectToString(brandRule.get("balance"));
                    BigDecimal bigDecimal = new BigDecimal(balance);
                    balanceList.add(bigDecimal);
                } else {
                    balanceList.add(new BigDecimal(totalAmt));
                }*/
            } else {
                Map brandRule = brandRules.get(0);
                Double balance = (Double) brandRule.get("balance");
                balanceList.add(new BigDecimal(balance));
            }
        }
        if (balanceList.isEmpty()) {
            balanceList.add(totalAmt);
        }
        BigDecimal min = Collections.min(balanceList);
        return min.setScale(2,BigDecimal.ROUND_HALF_UP);

    }

    @Override
    public void deleteCart(DeleteCartVo cartVo) {
        cartMapper.deleteCart(cartVo);
    }


    @Override
    public Map getCartListRule(Integer userId, Integer brandId) {
        Map map = cartMapper.getBrandCartTotal(userId, brandId);
        BigDecimal totalAmount = (BigDecimal) map.get("totalAmt");
        BigDecimal totalQuantity = (BigDecimal) map.get("totalQty");
        String miniQty = (String) map.get("miniQty");
        //计算阶梯价格
        String content = calculateLadderPrice(brandId, totalAmount, totalQuantity.intValue());
        Map productMap = new HashMap();
        productMap.put("content", content);
        productMap.put("totalQty",totalQuantity);
        productMap.put("miniQty",miniQty);
        BigDecimal balance = calculateLadderPrice1(brandId, totalAmount, totalQuantity.intValue());
        productMap.put("balance",balance);

        return productMap;
    }

}
